#include "Jeu.h"
#include "Jeu_private.h"

/* Constructor */
Jeu* newJeu(){
	Jeu* j;
	
	j = emalloc(sizeof(Jeu));
	if(j == NULL) return NULL;
	
	jeuSetMode(j,mjPlateau);
	jeuSetJoueurs(j,newList());
	jeuSetIt(j,newListIt(jeuGetJoueurs(j)));
	jeuSetPlateau(j,newPlateau(j));
	jeuSetHero(j,NULL);
	
	plateauInit(jeuGetPlateau(j));

	return j;
}

/* Destructor */
void deleteJeu(Jeu* jeu){
	Joueur* j;
	eassert(jeu != NULL);
	
	/* TODO : freeJeuCombat ... */
	listForEach(j,jeuGetJoueurs(jeu)){
		deleteJoueur(j);
	}
	deleteListIt(jeu->it);
	deleteList(jeu->joueurs);
	
	deletePlateau(jeu->plateau);
	free(jeu);
}

/* Getters */
ModeJeu jeuGetMode(Jeu* jeu){
	return jeu->mode;
}
Plateau* jeuGetPlateau(Jeu* jeu){
	return jeu->plateau;
}

List* jeuGetJoueurs(Jeu* jeu){
	eassert(jeu != NULL);
	
	return jeu->joueurs;
}

ListIterator* jeuGetIt(Jeu* jeu){
	eassert(jeu != NULL);
	
	return jeu->it;
}

Personnage* jeuGetHero(Jeu* jeu){
	eassert(jeu != NULL);
	
	return jeu->hero;
}

int jeuGetNbJoueurs(Jeu* jeu){
	eassert(jeu != NULL);
	
	return listGetSize(jeuGetJoueurs(jeu));
}

int jeuIsFini(Jeu* jeu){
	eassert(jeu != NULL);
	
	return jeu->fini;
}

/* Settlers */
void jeuSetPlateau(Jeu* jeu,Plateau* p){
	eassert(jeu != NULL);

	jeu->plateau = p;
	
	if(p != NULL && plateauGetJeu(p) != jeu)
		plateauSetJeu(p,jeu);
}
void jeuSetJoueurs(Jeu* jeu,List* joueurs){
	eassert(jeu != NULL);
	
	jeu->joueurs = joueurs;
}
void jeuSetIt(Jeu* jeu,ListIterator* it){
	eassert(jeu != NULL);
	
	jeu->it = it;
}

void jeuAddJoueur(Jeu* jeu,Joueur* joueur){
	eassert(jeu != NULL);
	eassert(jeuGetJoueurs(jeu) != NULL);
	
	listInsertLast(jeuGetJoueurs(jeu),joueur);
}
void jeuRemJoueur(Jeu* jeu,Joueur* joueur){
	eassert(jeu != NULL);
	eassert(jeuGetJoueurs(jeu) != NULL);
		
	listRem(jeuGetJoueurs(jeu),joueur);
}

void jeuSetHero(Jeu* jeu,Personnage* hero){
	eassert(jeu != NULL);
	
	jeu->hero = hero;
}
void jeuSetMode(Jeu* jeu,ModeJeu mj){
	eassert(jeu != NULL);
	
	jeu->mode = mj;
}

void jeuSetFini(Jeu* jeu){
	eassert(jeu != NULL);
	
	jeu->fini = 1;
}

/* Méthodes */
int jeuExecuter(Jeu* jeu){
	Case* c;
	Personnage* hero;
	ListIterator* it;
	Joueur* joueur;
	Pouvoir* pouvoir;
	Plateau* plateau;
	int nbCases;
	
	eassert(jeu != NULL);
	if(jeuGetNbJoueurs(jeu) < 2) return 0;
	
	plateau = jeuGetPlateau(jeu);
	hero = jeuGetHero(jeu);
	it = jeuGetIt(jeu);
	
	while(!jeuIsFini(jeu)){
		
		hero = jeuGetNextHero(jeu);
		
		/* si le héro est mort (le pauvre..)
		 * on le.. hop là! t'es revivant tout beau tout neuf */
		if(persoIsMort(hero)){
			persoRessuciter(hero);
			plateauPlacerEn(plateau,plateauGetCaseDepart(plateau),hero);
		}
		
		/* Utilise un pouvoir spécial si possible */
		pouvoir = persoGetPouvoir(hero);
		if(pouvoirCanUseItNow(pouvoir,jeu)){
			joueur = persoGetJoueur(hero);
			if(joueurAskUsePouvoir(joueur,pouvoir))
				pouvoirAppliquer(pouvoir,jeu);
		}
		
		c = persoGetCase(hero);
		caseExecuterSortie(c);
		
		/* Si il est bloqué.. ba tanpis pour lui :p */
		if(persoIsFreezed(hero)){
			persoUnFreeze(hero);
			continue;
		}
		
		nbCases = desLancer6();
		c = plateauAvancer(jeuGetPlateau(jeu),hero,nbCases);
		caseExecuter(c);
	}
	
	return 1;
}

Personnage* jeuGetNextHero(Jeu* jeu){
	Joueur* joueur;
	Personnage* perso;
	
	while((joueur = listItGetNext(jeuGetIt(jeu))) == NULL);
	perso = joueurGetNextHero(joueur);
	
	return perso;
}
